# RawHTTPServer.py
#
# Copyright (c) 2006 Michael Hobbs
#
# This file is part of iTorrent.
#
# iTorrent is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# iTorrent is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iTorrent; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


import SocketServer
import BaseHTTPServer
from StringIO import StringIO

from BitTorrent.platform import bttime


class RawHTTPServer(SocketServer.BaseServer):
	def __init__(self, rawServer, serverAddress, handlerClass):
		SocketServer.BaseServer.__init__(self, serverAddress, handlerClass)
		self.rawServer = rawServer
		self.server_bind()
		self.server_activate()
		self.lastConnection = None

	def server_bind(self):
		host, port = self.server_address
		# TODO: move message telling user to select a different port to here:
		self.socket = self.rawServer.create_serversocket(port, host)
		self.address = self.socket.getsockname()

	def server_activate(self):
		self.rawServer.start_listening(self.socket, self)

	def connection_made(self, socket):
		self.lastConnection = (socket, (socket.ip, socket.port))
		self.handle_request()

	def get_request(self):
		return self.lastConnection


# TODO: Add all handler methods to class
class RawHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
	def setup(self):
		self.socket = self.request
		self.socket.handler = self
		self.rfile = StringIO()
		self.rfilePos = 0
		self.wfile = SingleSocketWriter(self.socket)

	def handle(self):
		pass

	def finish(self):
		pass

	def data_came_in(self, socket, data):
		self.rfile.write(data)
		self.rfile.seek(0, self.rfilePos)
		if self.rfile.read().find('\r\n\r\n') >= 0:
			self.rfile.seek(0, self.rfilePos)
			self.done = False
			self.handle_one_request()
			if self.done:
				socket.close()
				return
			self.rfilePos = self.rfile.tell()
		# TODO: Check close_connection (a la BaseHTTPRequestHandler.handle())

	def connection_flushed(self, unused_socket):
		self.wfile.flushed()


class SingleSocketWriter(object):
	def __init__(self, socket):
		super(SingleSocketWriter, self).__init__()
		self.socket = socket
		self.flushCallback = None

	def write(self, data):
		self.socket.last_hit = bttime()
		self.socket.write(data)
		return self.socket.is_flushed()

	def close(self):
		self.socket.close()

	def isClosed(self):
		return (self.socket.socket is None)

	def onFlush(self, callback, *args, **kwargs):
		self.flushCallback = (callback, args, kwargs)

	def flushed(self):
		if not self.flushCallback:
			return
		callback, args, kwargs = self.flushCallback
		callback(*args, **kwargs)
